#include "TestEngine.h"
#include <cstddef>
#include <cstdint>
#include <thread>
#include "DateTime.h"
#include "Logger.h"
#include "OnTestMsg.h"
#include "XnccType.h"

using namespace std::placeholders;
using namespace xncc::user;
using namespace xncc::types;
static constexpr queue_id_t TEST_MSG_CHANNEL         = 1000;
static constexpr queue_id_t TEST_MSG_CHANNEL_NO_LOCK = 1001;

TYPE_MESSAGE_ID_BIND(OnTestMsg, 1000);

static void handleSendMsg()
{
    static int i = 0;
    while (true) {
        OnTestMsg realMsg;
        realMsg.init(++i);
        TestEngine::sendDataWithLock(realMsg.data_, realMsg.len(), MessageTraits<OnTestMsg>::ID, TEST_MSG_CHANNEL);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        LOG_INFO(CONSOLE_LOG) << "send test msg = " << i;
    }
}

static void handleSendMsg2()
{
    static int i = 1000000;
    while (true) {
        OnTestMsg realMsg;
        realMsg.init(++i);
        TestEngine::sendDataWithLock(realMsg.data_, realMsg.len(), MessageTraits<OnTestMsg>::ID, TEST_MSG_CHANNEL);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        LOG_INFO(CONSOLE_LOG) << "send test msg = " << i;
    }
}

static void handleSendMsg3()
{
    static int i = 3000000;
    while (true) {
        OnTestMsg realMsg;
        realMsg.init(++i);
        TestEngine::sendDataWithLock(realMsg.data_, realMsg.len(), MessageTraits<OnTestMsg>::ID, TEST_MSG_CHANNEL);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        LOG_INFO(CONSOLE_LOG) << "send test msg = " << i;
    }
}

TestEngine::TestEngine() : EventEngine(1)
{
}

void TestEngine::init()
{
    int ret = subQueue(TEST_MSG_CHANNEL, 1024, true);
    if (ret) {
        LOG_INFO(CONSOLE_LOG) << "init sub queue failed";
        return;
    }
    ret = subQueue(TEST_MSG_CHANNEL_NO_LOCK, 1024, true);
    if (ret) {
        LOG_INFO(CONSOLE_LOG) << "init sub queue failed";
        return;
    }
    auto testFunc = std::bind(&TestEngine::handleTestMsg, this, _1, _2, _3, _4);
    registerUserFunc(MessageTraits<OnTestMsg>::ID, testFunc);
    std::thread t(handleSendMsg);
    t.detach();
    std::thread t1(handleSendMsg2);
    t1.detach();
    std::thread t2(handleSendMsg3);
    t2.detach();

    id_ = setTimerFunc(DateTime::timeMicro(), 1000000, std::bind(&TestEngine::printTimerNow, this));
    if (id_ == INVALID_TIMER_ID) {
        LOG_ERROR(CONSOLE_LOG) << "create timer 2 faild";
    }
}

void TestEngine::handleTestMsg(const char* msg, uint32_t len, thread_id_t tid, connection_id_t connId)
{
    LOG_INFO(CONSOLE_LOG) << "receive test msg = " << std::string(msg, static_cast<std::size_t>(len));
}

void TestEngine::printTimerNow()
{
    static int i = 1;
    LOG_INFO(CONSOLE_LOG) << "time now = " << DateTime::nowLocal().toString();
    if (i++ == 10) {
        cancelTimer(id_);
    }
}
